<template>
  <el-dialog v-model="localVisible" :title="title" :width="width" :before-close="handleClose">
    <el-scrollbar max-height="70vh">
      <!-- 这里可以放置你的对话框内容 -->
      <el-form
        class="form"
        ref="formEl"
        :model="localFormParams"
        :label-width="labelWidth"
        :style="{ maxWidth: maxWidth }"
        :rules="rules"
      >
        <!-- 动态生成表单项 -->
        <el-form-item
          v-for="(item, index) in itemConfig"
          :key="index"
          :label="item.label"
          :prop="item.prop"
        >
          <!--输入框-->
          <template v-if="item.type == ComponentEnum.INPUT">
            <el-input v-model="localFormParams[item.field]" v-bind="item.attribute" />
          </template>
          <!--单选框组-->
          <template v-else-if="item.type == ComponentEnum.RADIO_GROUP">
            <el-radio-group v-bind="item.attribute" v-model="localFormParams[item.field]">
              <el-radio v-for="(ele, i) in item.options" :key="i" v-bind="ele">
                {{ ele.label }}
              </el-radio>
            </el-radio-group>
          </template>
          <!--多选框组-->
          <template v-else-if="item.type == ComponentEnum.CHECKBOX_GROUP">
            <el-checkbox-group v-bind="item.attribute"  v-model="localFormParams[item.field]">
              <el-checkbox v-for="(ele, i) in item.options" :key="i" v-bind="ele" />
            </el-checkbox-group>
          </template>
          <!--数值输入框-->
          <template v-else-if="item.type == ComponentEnum.INPUT_NUMBER">
            <el-input-number v-model="localFormParams[item.field]" v-bind="item.attribute" />
          </template>
          <!--下拉选择框-->
          <template v-else-if="item.type == ComponentEnum.SELECT">
            <el-select
              v-model="localFormParams[item.field]"
              placeholder="请选择"
              v-bind="item.attribute"
            >
              <el-option v-for="(ele, i) in item.options" :key="i" v-bind="ele" />
            </el-select>
          </template>
          <!--Switch 开关-->
          <template v-else-if="item.type == ComponentEnum.SWITCH">
            <el-switch
              v-model="localFormParams[item.field]"
              inline-prompt
              v-bind="item.attribute"
            />
          </template>
          <!--自定义组件-->
          <template v-else-if="item.type == ComponentEnum.CUSTOMIZE">
            <template v-if="item.options?.attributeMethod">
              <component
                :is="item.component"
                v-model="localFormParams[item.field]"
                v-bind="item.attribute(localFormParams)"
              />
            </template>
            <template v-else>
              <component
                :is="item.component"
                v-model="localFormParams[item.field]"
                v-bind="item.attribute"
              />
            </template>
          </template>
          <!--标签-->
          <template v-else-if="item.type == ComponentEnum.LABEL">
            {{ localFormParams[item.field] }}
          </template>
          <!--文件上传-->
          <template v-else-if="item.type == ComponentEnum.UPLOAD">
            <el-upload
              v-bind="item.attribute"
              v-model:file-list="item.options.fileList"
              :action="item.options.action"
              :on-success="
                (response: ResultTypes) => item.options.method.success(response, localFormParams)
              "
            >
              <template v-if="item.options.isActor">
                <img
                  style="width: 100px; height: 100px"
                  v-if="localFormParams[item.field]"
                  :src="localFormParams[item.field]"
                  class="avatar"
                  alt="暂无图片"
                />
                <el-icon v-else class="avatar-uploader-icon">
                  <Plus />
                </el-icon>
              </template>
              <template v-else>
                <el-button type="primary">选择文件</el-button>
              </template>
            </el-upload>
          </template>
        </el-form-item>
        <slot></slot>
        <el-form-item>
          <div style="display: flex; justify-content: flex-end; width: 100%">
            <template v-if="localSubmit">
              <el-button type="primary" @click="onSubmit" :loading="loading"
                >{{ submitText }}
              </el-button>
              <el-button text @click="channel">{{ cancelText }}</el-button>
            </template>
            <template v-else>
              <el-button type="primary" @click="channel">{{ submitText }}</el-button>
            </template>
          </div>
        </el-form-item>
      </el-form>
    </el-scrollbar>
  </el-dialog>
</template>

<script lang="ts">
/**
 * 动态生成表单项
 *
 *
 * @property {string} label - 表单项名称
 * @property {string} prop - 表单项的 prop，用于验证和绑定
 * @property {string} field - 绑定的数据字段名称
 * @property {ComponentEnum} type - 表单项类型
 * @property {any} component - 表单项组件
 * @property {any} attribute - 表单项外层组件参数，使用 v-bind 绑定属性
 * @property {any} options - 表单项内层组件参数，使用 v-bind 绑定属性
 *
 *
 */
export interface FormItemConfig {
  label: string
  prop: string
  field: string
  type: ComponentEnum
  attribute?: any
  component?: any
  options?: any
}

/**
 * Form 组件参数类型
 * @property {string} title - 标题
 * @property {string} width - 宽度
 * @property {Array<FormItemConfig>} itemConfig - 动态生成表单项
 * @property {boolean} closeTips - 是否显示关闭提示
 * @property {any} rules - 表单验证规则
 * @property {string} labelWidth - 标签宽度
 * @property {string} submitText - 提交按钮文本
 * @property {string} cancelText - 取消按钮文本
 * @property {string} maxWidth - 最大宽度
 */
export interface FormItemProps {
  title?: string
  width?: string
  itemConfig: Array<FormItemConfig>
  closeTips?: boolean
  rules?: any
  labelWidth?: string
  submitText?: string
  cancelText?: string
  maxWidth?: string
}

/**
 * 组件类型
 * @property {string} INPUT - 输入框
 * @property {string} INPUT_NUMBER - 数字输入框
 * @property {string} SELECT - 下拉选择框
 * @property {string} RADIO_GROUP - 单选框
 * @property {string} CUSTOMIZE - 自定义组件
 * @property {string} CHECKBOX_GROUP - 复选框
 * @property {string} SWITCH - 开关
 */
export enum ComponentEnum {
  INPUT = 'Input',
  INPUT_NUMBER = 'InputNumber',
  SELECT = 'Select',
  RADIO_GROUP = 'RadioGroup',
  CUSTOMIZE = 'Customize',
  CHECKBOX_GROUP = 'CheckboxGroup',
  SWITCH = 'Switch',
  UPLOAD = 'Upload',
  LABEL = 'label'
}
</script>
<script setup lang="ts">
import { ref, toRaw } from 'vue'
import { ElMessageBox, ElNotification, type FormInstance } from 'element-plus'
import type { ResultTypes } from '@/resources/interface/ResultTypes'
import { Plus } from '@element-plus/icons-vue'

//定义组件的 props
const props = withDefaults(defineProps<FormItemProps>(), {
  title: '弹框',
  width: '20%',
  closeTips: true,
  rules: () => {},
  labelWidth: '30%',
  submitText: '确定',
  cancelText: '取消',
  maxWidth: '90%'
})

const formEl = ref<FormInstance>()
let localFormParams = defineModel<any>('formParams')
const localVisible = defineModel<boolean>('visible')
const loading = defineModel<boolean>('hasLoading')
const localSubmit = defineModel<boolean>('isSubmit')
// 定义事件发射器
const emit = defineEmits(['submit'])

// ----------------------------------方法区--------------------------------
const onSubmit = async () => {
  if (!formEl.value) return
  await formEl.value.validate((valid) => {
    loading.value = true
    if (valid) {
      localVisible.value = false
      emit('submit', toRaw(localFormParams.value))
    } else {
      ElNotification.error('请填写正确的信息')
      loading.value = false
    }
  })
}

const resetForm = () => {
  if (!formEl.value) return
  formEl.value.resetFields()
}

const channel = () => {
  if (props.closeTips) {
    ElMessageBox.confirm('确定关闭该窗口?', {
      confirmButtonText: '确定',
      buttonSize: 'small',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        resetForm()
        localVisible.value = false // 使用 localVisible 来发射关闭事件
      })
      .catch(() => {
        // 处理取消操作或错误
      })
  } else {
    resetForm()
    localVisible.value = false // 使用 localVisible 来发射关闭事件
  }
}
// 关闭对话框时的处理逻辑
const handleClose = (done: () => void) => {
  if (props.closeTips) {
    ElMessageBox.confirm('确定关闭该窗口?', {
      confirmButtonText: '确定',
      buttonSize: 'small',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        resetForm()
        done()
        localVisible.value = false // 使用 localVisible 来发射关闭事件
      })
      .catch(() => {
        // 处理取消操作或错误
      })
  } else {
    done()
  }
}
</script>
<style scoped>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 100px;
  height: 100px;
  text-align: center;
}
</style>
